package com.tanker.util;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.tanker.common.ErrorCode;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;
import java.util.Random;

/**
 * @author xqxue
 * @time 2017年9月19日 下午2:39:09
 */
@org.springframework.stereotype.Component
public class OSSClientUtil {
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	// endpoint以杭州为例，其它region请按实际情况填写
	//private String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
	private String endpoint = "http://oss-cn-shanghai.aliyuncs.com";
	// accessKey
	//private String accessKeyId = "XakvqZLxRN1DR9Iy";
	//private String accessKeySecret = "6GNGlPXmKe3uKC1GQJs5avnRHuOeE2";
	private String accessKeyId = "LTAIFgq6pbnajExW";
	private String accessKeySecret = "uUoAXN0cwq8WFHSltFgXAOzi62akOb";
	// 空间
	private String bucketName = "tanker-images-test";
	// 文件存储目录
	private String filedir = "tanker/console/";

	private OSSClient ossClient;

	public OSSClientUtil() {
		/*ClientConfiguration conf = new ClientConfiguration();
		// 设置HTTP最大连接数为10
		conf.setMaxConnections(10);
		// 设置TCP连接超时为5000毫秒
		conf.setConnectionTimeout(5000);
		// 设置最大的重试次数为3
		conf.setMaxErrorRetry(3);
		// 设置Socket传输数据超时的时间为2000毫秒
		conf.setSocketTimeout(10000);*/
		ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
	}

	/**
	 * 销毁
	 */
	public void destory() {
		// ossClient.shutdown();
	}

	public String uploadImg2Oss(MultipartFile file, int memNo) {
		String originalFilename = file.getOriginalFilename();
		String substring = originalFilename.substring(
				originalFilename.lastIndexOf(".")).toLowerCase();
		Random random = new Random();
		String name = random.nextInt(10000) + System.currentTimeMillis()
				+ substring;
		InputStream inputStream = null;
		String path = memNo + "/" + name;
		try {
			inputStream = file.getInputStream();
			this.uploadFile2OSS(inputStream, path, memNo);
			return path;
		} catch (Exception e) {
			logger.error("上传图片失败 ");
			e.printStackTrace();
		} finally {
			try {
				if(inputStream!=null)
					inputStream.close();
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	  /**
     * 上传文件 至 bucket at-images
     * @param key
     * @param base64
     * @param verifyCode 文件MD5值
     * @return
     * @throws Exception
     */
    public ErrorCode upload(String key, String base64, String verifyCode) throws Exception{
    	ErrorCode errorCode = ErrorCode.FAILED;
    	InputStream	input = null;
    	ObjectMetadata objectMeta = new ObjectMetadata();
        objectMeta.setContentType("image/*");//在metadata中标记文件类型
    	try {
	        //byte[] bytes = new BASE64Decoder().decodeBuffer(base64);
    		byte[] bytes = Base64.decodeBase64(base64);
	        objectMeta.setContentLength(bytes.length);
	        input = new ByteArrayInputStream(bytes);
			PutObjectResult	res = ossClient.putObject(bucketName, key, input, objectMeta);
			//logger.info("Res MD5:"+res.getETag());
			errorCode = ErrorCode.SUCCESS;
			//校验文件MD5值
			/*if(verifyCode.equalsIgnoreCase(res.getETag()) == true){
				logger.info("文件上传成功：{}",key);
				errorCode = ErrorCode.SUCCESS;
			}else{
				logger.error("文件上传失败：{}",key);
			}*/
		} catch (Exception e) {
			//logger.error("",e);
		}finally{
			if(input != null){
				input.close();
			}
		}
        return errorCode;
    }

	public String uploadImg2Oss(String base64, int memNo) {
		Random random = new Random();
		String name = random.nextInt(10000) + System.currentTimeMillis()
				+ ".jpg";
		InputStream inputStream = null;
		String path = memNo + "/" + name;
		try {
			byte[] bytes = Base64.decodeBase64(base64);
	        inputStream = new ByteArrayInputStream(bytes);
			this.uploadFile2OSS(inputStream, path, memNo);
			return path;
		} catch (Exception e) {
			logger.error("上传图片失败 ");
			e.printStackTrace();
		} finally {
			try {
				if(inputStream!=null)
					inputStream.close();
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public String uploadImg2Os(String base64, String memNo,String picURL) {
		Random random = new Random();
		String name = random.nextInt(10000) + System.currentTimeMillis()
				+ ".jpg";
		InputStream inputStream = null;
		String path = memNo + "/" + name;
		try {
			byte[] bytes = Base64.decodeBase64(base64);
	        inputStream = new ByteArrayInputStream(bytes);
			this.uploadFile2OS(inputStream, path, picURL);
			return path;
		} catch (Exception e) {
			logger.error("上传图片失败 ");
			e.printStackTrace();
		} finally {
			try {
				if(inputStream!=null)
					inputStream.close();
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * 车场图片上传，压缩图片大小
	 * @param base64
	 * @param memNo
	 * @param picURL
	 * @param type
     * @return
     */
	public String uploadImgToOs(String base64, String memNo,String picURL,String type) {
		Random random = new Random();
		String name = random.nextInt(10000) + System.currentTimeMillis()
				+ "."+type;
		InputStream inputStream = null;
		String path = memNo + "/" + name;
		try {
			byte[] bytes = Base64.decodeBase64(base64);
			inputStream = new ByteArrayInputStream(bytes);
//			OutputStream os = parse(inputStream);
			OutputStream os = resizeImage(inputStream,null,750,type);
			inputStream = parse(os);
			this.uploadFile2OS(inputStream, path, picURL);
			return path;
		} catch (Exception e) {
			logger.error("上传图片失败 ");
			e.printStackTrace();
		} finally {
			try {
				if(inputStream!=null)
					inputStream.close();
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}



	public static OutputStream resizeImage(InputStream is, OutputStream os, int size, String format) throws Exception {
		BufferedImage prevImage = ImageIO.read(is);
		double width = prevImage.getWidth();
		double height = prevImage.getHeight();
		double percent = size/width;
		int newWidth = (int)(width * percent);
		int newHeight = (int)(height * percent);
		BufferedImage image = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_BGR);
		Graphics graphics = image.createGraphics();
		graphics.drawImage(prevImage, 0, 0, newWidth, newHeight, null);
		os = parse(is);
		ImageIO.write(image, format, os);
		os.flush();
		is.close();
		os.close();
		ByteArrayOutputStream b = (ByteArrayOutputStream) os;
		return os;
	}
	//inputStream转outputStream
	   public static ByteArrayOutputStream parse(InputStream in) throws Exception
	   {
		       ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
		       int ch;
		       while ((ch = in.read()) != -1) {
		             swapStream.write(ch);
			   }
			   return swapStream;
	   }
     //outputStream转inputStream
	 public static ByteArrayInputStream parse(OutputStream out) throws Exception
     {
	         ByteArrayOutputStream baos=new ByteArrayOutputStream();
	         baos=(ByteArrayOutputStream) out;
	         ByteArrayInputStream swapStream = new ByteArrayInputStream(baos.toByteArray());
	         return swapStream;
	     }

	/**
	 * 获得图片路径
	 * @param fileUrl
	 * @return
	 */
	public String getImgUrl(String fileUrl) {
		if (!StringUtils.isEmpty(fileUrl)) {
			String[] split = fileUrl.split("/");
			return this.getUrl(this.filedir + split[split.length - 1]);
		}
		return "";
	}

	/**
	 * 上传到OSS服务器 如果同名文件会覆盖服务器上的
	 * @param instream 文件流
	 * @param fileName  文件名称 包括后缀名
	 * @return 出错返回"" ,唯一MD5数字签名
	 */
	public String uploadFile2OSS(InputStream instream, String fileName, int memNo) {
		String ret = "";
		try {
			// 创建上传Object的Metadata
			ObjectMetadata objectMetadata = new ObjectMetadata();
			objectMetadata.setContentType("image/*");// 在metadata中标记文件类型
			// objectMetadata.setContentLength(instream.available());
			// objectMetadata.setCacheControl("no-cache");
			// objectMetadata.setHeader("Pragma", "no-cache");
			// objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
			// objectMetadata.setContentDisposition("inline;filename=" +
			// fileName);
			// 上传文件
			PutObjectResult putResult = ossClient.putObject(bucketName, filedir + fileName, instream, objectMetadata);
			ret = putResult.getETag();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		} finally {
			try {
				if (instream != null) {
					instream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return ret;
	}

	/**
	 * 上传到OSS服务器 如果同名文件会覆盖服务器上的
	 * @param instream 文件流
	 * @param fileName  文件名称 包括后缀名
	 * @return 出错返回"" ,唯一MD5数字签名
	 */
	public String uploadFile2OS(InputStream instream, String fileName, String url) {
		String ret = "";
		try {
			// 创建上传Object的Metadata
			ObjectMetadata objectMetadata = new ObjectMetadata();
			objectMetadata.setContentType("image/*");// 在metadata中标记文件类型
			// objectMetadata.setContentLength(instream.available());
			// objectMetadata.setCacheControl("no-cache");
			// objectMetadata.setHeader("Pragma", "no-cache");
			// objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
			// objectMetadata.setContentDisposition("inline;filename=" +
			// fileName);
			// 上传文件
			PutObjectResult putResult = null;
			if(StringUtil.nullOrBlank(url)){
				 putResult = ossClient.putObject(bucketName, filedir+fileName, instream, objectMetadata);
			}else{
				 putResult = ossClient.putObject(bucketName, fileName, instream, objectMetadata);
			}
			ret = putResult.getETag();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		} finally {
			try {
				if (instream != null) {
					instream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return ret;
	}


	/**
	 * Description: 判断OSS服务文件上传时文件的contentType
	 * @param FilenameExtension  文件后缀
	 */
	public static String getContentType(String FilenameExtension) {
		if (FilenameExtension.equalsIgnoreCase("bmp")) {
			return "image/bmp";
		}
		if (FilenameExtension.equalsIgnoreCase("gif")) {
			return "image/gif";
		}
		if (FilenameExtension.equalsIgnoreCase("jpeg")
				|| FilenameExtension.equalsIgnoreCase("jpg")
				|| FilenameExtension.equalsIgnoreCase("png")) {
			return "image/jpeg";
		}
		if (FilenameExtension.equalsIgnoreCase("html")) {
			return "text/html";
		}
		if (FilenameExtension.equalsIgnoreCase("txt")) {
			return "text/plain";
		}
		if (FilenameExtension.equalsIgnoreCase("vsd")) {
			return "application/vnd.visio";
		}
		if (FilenameExtension.equalsIgnoreCase("pptx")
				|| FilenameExtension.equalsIgnoreCase("ppt")) {
			return "application/vnd.ms-powerpoint";
		}
		if (FilenameExtension.equalsIgnoreCase("docx")
				|| FilenameExtension.equalsIgnoreCase("doc")) {
			return "application/msword";
		}
		if (FilenameExtension.equalsIgnoreCase("xml")) {
			return "text/xml";
		}
		return "image/jpeg";
	}

	/**
	 * 获得url链接
	 * @param key
	 * @return
	 */
	public String getUrl(String key) {
		String url = "";
		if (!StringUtils.isEmpty(key)) {
			// 设置URL过期时间为10年 3600l* 1000*24*365*10
			Date expiration = new Date(new Date().getTime() + 3600l * 1000 * 24
					* 365 * 10);
			// 生成URL
			String path = this.filedir + key;
			URL u = ossClient.generatePresignedUrl(bucketName, path, expiration);
			if (u != null) {
				url = "https://" + u.getAuthority() + u.getPath();
			}
		}

		return url;
	}

	public String getEndpoint() {
		return endpoint;
	}

	public void setEndpoint(String endpoint) {
		this.endpoint = endpoint;
	}

	public String getAccessKeyId() {
		return accessKeyId;
	}

	public void setAccessKeyId(String accessKeyId) {
		this.accessKeyId = accessKeyId;
	}

	public String getAccessKeySecret() {
		return accessKeySecret;
	}

	public void setAccessKeySecret(String accessKeySecret) {
		this.accessKeySecret = accessKeySecret;
	}

	public String getBucketName() {
		return bucketName;
	}

	public void setBucketName(String bucketName) {
		this.bucketName = bucketName;
	}

}
